// ignore_for_file: depend_on_referenced_packages

import 'dart:ffi';

import 'package:flutter_2b_client/apis/MarketDeliveryOrderApi.dart';
import 'package:flutter_2b_client/json/LocalDateConverter.dart';
import 'package:flutter_2b_client/json/LocalDateTimeConverter.dart';
import 'package:flutter_2b_client/model/IntIdAndName.dart';
import 'package:flutter_2b_client/utils/Page.dart';
import 'package:flutter_2b_client/utils/local_datetime.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:retrofit/dio.dart';
import 'package:retrofit/http.dart';
import 'package:dio/dio.dart';

import '../model/NullableLocalDateRange.dart';
import 'Initial.dart';

part 'CheckInventoryRecordApi.g.dart';

part 'CheckInventoryRecordApi.freezed.dart';

@RestApi()
abstract class CheckInventoryRecordApi {
  factory CheckInventoryRecordApi(Dio dio, {String baseUrl}) =
      _CheckInventoryRecordApi;

  @GET("checkInventoryRecords")
  Future<Page<QueryCheckInventoryRecordResponse>> _queryCheckInventoryRecords(
      @Queries() Map<String, dynamic> queries);

  @GET("checkInventoryRecords/employees?projection=summary")
  Future<List<IntIdAndName>> getAllCheckInventoryRecordCreatedEmployees();

  @GET("createdDateRanges")
  Future<NullableLocalDateRange> getAllCheckInventoryRecordCreatedDateRange();

  @POST("checkInventoryRecords")
  Future<QueryCheckInventoryRecordResponse> createCheckInventoryRecord(
      @Body() CreateCheckInventoryRecordRequest request);

  @GET("checkInventoryRecords/{id}")
  Future<CheckInventoryRecordDetail> getCheckInventoryRecordDetail(
      @Path("id") int id);

  @GET("checkInventoryRecords/{id}/items")
  Future<Page<CheckInventoryRecordItemSummary>> _queryCheckInventoryRecordItems(
      @Path() int id, @Queries() Map<String, dynamic> queries);

  @PATCH("checkInventoryRecords/{id}/submit")
  Future<void> submitCheckInventoryRecord(@Path() int id);

  @POST("checkInventoryRecords/{id}/items/goods/{goodsId}")
  Future<CheckInventoryRecordItemSummary> addGoodsByGoodsId(
      @Path() int id, @Path("goodsId") int goodsId);

  @POST("checkInventoryRecords/{id}/items/barcodes/{barcode}")
  Future<CheckInventoryRecordItemSummary> addGoodsByGoodsBarcode(
      @Path() int id, @Path("barcode") String barcode);

  @DELETE("checkInventoryRecords/{id}/items/{goodsId}")
  Future<void> deleteCheckInventory(@Path() int id, @Path("goodsId") int goodsId);

  @PATCH("checkInventoryRecords/{id}/items/{goodsId}/amount")
  Future<void> updateItemAmount(@Path()int id, @Path()int goodsId, @Body() UpdateItemAmountRequest updateItemAmountRequest);

  @GET("checkInventoryRecords/{id}/items/barcodes/{barcode}/exists")
  Future<bool> exists(@Path()int id, @Path()String barcode);

  @DioResponseType(ResponseType.bytes)
  @GET("checkInventoryRecords/{id}/excel")
  Future<List<int>> exportToExcel(@Path() int id,@Query("fields") List<String>? fields);

}

extension CheckInventoryRecordApiExtension on CheckInventoryRecordApi {
  Future<Page<QueryCheckInventoryRecordResponse>> queryCheckInventoryRecords(
      QueryCheckInventoryRecordRequest request, Pageable pageable) {
    return _queryCheckInventoryRecords(
        {...pageable.toRequestParamsMap(), ...request.toJson()});
  }

  Future<Page<CheckInventoryRecordItemSummary>> queryCheckInventoryRecordItems(
      int id, Pageable pageable) {
    return _queryCheckInventoryRecordItems(id, pageable.toRequestParamsMap());
  }
}

@freezed
class CheckInventoryRecordItemSummary with _$CheckInventoryRecordItemSummary {
  const factory CheckInventoryRecordItemSummary({
    required int goodsId,
    required String name,
    required String barcode,
    required int amount,
    required int inStore,
    required String? boxSpecification,
  }) = _CheckInventoryRecordItemSummary;

  const CheckInventoryRecordItemSummary._();

  factory CheckInventoryRecordItemSummary.fromJson(Map<String, dynamic> json) =>
      _$CheckInventoryRecordItemSummaryFromJson(json);
}

@freezed
class CheckInventoryRecordDetail with _$CheckInventoryRecordDetail {
  const factory CheckInventoryRecordDetail({
    required int id,
    @LocalDateTimeConverter() required LocalDateTime createdDateTime,
    required String name,
    required IntIdAndName createdBy,
    @LocalDateTimeConverter() required LocalDateTime? submittedDateTime,
  }) = _CheckInventoryRecordDetail;

  const CheckInventoryRecordDetail._();

  factory CheckInventoryRecordDetail.fromJson(Map<String, dynamic> json) =>
      _$CheckInventoryRecordDetailFromJson(json);
}

@freezed
class CreateCheckInventoryRecordRequest
    with _$CreateCheckInventoryRecordRequest {
  const factory CreateCheckInventoryRecordRequest({
    String? name,
  }) = _CreateCheckInventoryRecordRequest;

  const CreateCheckInventoryRecordRequest._();

  factory CreateCheckInventoryRecordRequest.fromJson(
          Map<String, dynamic> json) =>
      _$CreateCheckInventoryRecordRequestFromJson(json);
}

@freezed
class QueryCheckInventoryRecordResponse
    with _$QueryCheckInventoryRecordResponse {
  const factory QueryCheckInventoryRecordResponse(
          {required int id,
          required IntIdAndName createdBy,
          @LocalDateTimeConverter() required LocalDateTime createdDateTime,
          required int goodsKindAmount,
          required String name,
          @LocalDateTimeConverter() LocalDateTime? submittedDateTime}) =
      _QueryCheckInventoryRecordResponse;

  const QueryCheckInventoryRecordResponse._();

  factory QueryCheckInventoryRecordResponse.fromJson(
          Map<String, dynamic> json) =>
      _$QueryCheckInventoryRecordResponseFromJson(json);
}

@freezed
class QueryCheckInventoryRecordRequest with _$QueryCheckInventoryRecordRequest {
  const factory QueryCheckInventoryRecordRequest({
    @LocalDateConverter() LocalDate? startDate,
    @LocalDateConverter() LocalDate? endDate,
    @Default([]) List<int> employeeIds,
    bool? submitted,
  }) = _QueryCheckInventoryRecordRequest;

  const QueryCheckInventoryRecordRequest._();

  factory QueryCheckInventoryRecordRequest.fromJson(
          Map<String, dynamic> json) =>
      _$QueryCheckInventoryRecordRequestFromJson(json);

  bool hasAnyFilter() {
    return startDate != null ||
        endDate != null ||
        employeeIds.isNotEmpty ||
        submitted != null;
  }
}

CheckInventoryRecordApi checkInventoryRecordApi =
    CheckInventoryRecordApi(dio, baseUrl: baseUrl);
